#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
主窗口界面模块 - 实现GUI界面和用户交互
遵循单一职责原则，专门处理界面显示和用户操作

Copyright (c) 2025 RAYA-MAX
Quick-Start is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from typing import List, Dict, Any, Optional
import os

from config_manager import ConfigManager
from launcher import SoftwareLauncher
from dialogs import ModeManagerWindow, SoftwareEditWindow


class MainWindow:
    """主窗口类 - 处理GUI界面和用户交互"""
    
    def __init__(self):
        """初始化主窗口"""
        self.root = tk.Tk()
        self.config_manager = ConfigManager()
        self.launcher = SoftwareLauncher()
        
        # 界面状态变量
        self.current_mode = tk.StringVar(value=self.config_manager.get_current_mode())
        self.software_vars = []  # 复选框变量列表
        
        self._setup_window()
        self._create_widgets()
        self._refresh_software_list()
    
    def _setup_window(self):
        """设置窗口基本属性"""
        self.root.title("快速启动程序")
        self.root.geometry("800x600")
        self.root.minsize(600, 400)
        
        # 设置窗口图标（如果有的话）
        try:
            # self.root.iconbitmap("icon.ico")  # 可选：添加图标
            pass
        except:
            pass
    
    def _create_widgets(self):
        """创建界面组件"""
        # 创建主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 上部模式区域（30%）
        self._create_mode_frame(main_frame)
        
        # 下部软件区域（70%）
        self._create_software_frame(main_frame)
    
    def _create_mode_frame(self, parent):
        """创建模式选择和管理区域"""
        mode_frame = ttk.LabelFrame(parent, text="模式管理", padding=10)
        mode_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 模式选择按钮区域
        mode_buttons_frame = ttk.Frame(mode_frame)
        mode_buttons_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 获取所有模式并创建按钮
        modes = self.config_manager.get_modes()
        for mode in modes:
            btn = ttk.Button(
                mode_buttons_frame, 
                text=mode,
                command=lambda m=mode: self._switch_mode(m)
            )
            btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 模式管理按钮
        manage_btn = ttk.Button(
            mode_buttons_frame,
            text="模式管理",
            command=self._open_mode_manager
        )
        manage_btn.pack(side=tk.RIGHT)
        
        # 当前模式显示
        current_mode_label = ttk.Label(
            mode_frame,
            text=f"当前模式: {self.current_mode.get()}",
            font=("Arial", 10, "bold")
        )
        current_mode_label.pack(anchor=tk.W)
    
    def _create_software_frame(self, parent):
        """创建软件列表和操作区域"""
        software_frame = ttk.Frame(parent)
        software_frame.pack(fill=tk.BOTH, expand=True)
        
        # 左侧软件列表区域
        left_frame = ttk.LabelFrame(software_frame, text="软件列表", padding=10)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
        
        # 创建软件列表滚动区域
        self._create_software_list(left_frame)
        
        # 右侧操作区域
        right_frame = ttk.LabelFrame(software_frame, text="操作面板", padding=10)
        right_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=(5, 0))
        
        # 创建操作按钮
        self._create_operation_buttons(right_frame)
    
    def _create_software_list(self, parent):
        """创建软件列表显示区域"""
        # 创建滚动框架
        canvas = tk.Canvas(parent)
        scrollbar = ttk.Scrollbar(parent, orient="vertical", command=canvas.yview)
        self.scrollable_frame = ttk.Frame(canvas)
        
        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 绑定鼠标滚轮事件
        def _on_mousewheel(event):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        canvas.bind_all("<MouseWheel>", _on_mousewheel)
    
    def _create_operation_buttons(self, parent):
        """创建操作按钮区域"""
        # 软件管理按钮
        ttk.Label(parent, text="软件管理:", font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(0, 5))
        
        add_btn = ttk.Button(parent, text="添加软件", command=self._add_software)
        add_btn.pack(fill=tk.X, pady=2)
        
        edit_btn = ttk.Button(parent, text="编辑软件", command=self._edit_software)
        edit_btn.pack(fill=tk.X, pady=2)
        
        delete_btn = ttk.Button(parent, text="删除软件", command=self._delete_software)
        delete_btn.pack(fill=tk.X, pady=2)
        
        # 分隔线
        ttk.Separator(parent, orient='horizontal').pack(fill=tk.X, pady=10)
        
        # 选择操作按钮
        ttk.Label(parent, text="批量操作:", font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(0, 5))
        
        select_all_btn = ttk.Button(parent, text="全选", command=self._select_all)
        select_all_btn.pack(fill=tk.X, pady=2)
        
        deselect_all_btn = ttk.Button(parent, text="取消全选", command=self._deselect_all)
        deselect_all_btn.pack(fill=tk.X, pady=2)
        
        # 分隔线
        ttk.Separator(parent, orient='horizontal').pack(fill=tk.X, pady=10)
        
        # 启动操作按钮
        ttk.Label(parent, text="启动操作:", font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(0, 5))
        
        launch_selected_btn = ttk.Button(
            parent, 
            text="启动选中", 
            command=self._launch_selected,
            style="Accent.TButton"
        )
        launch_selected_btn.pack(fill=tk.X, pady=2)
        
        launch_all_btn = ttk.Button(
            parent, 
            text="启动全部", 
            command=self._launch_all,
            style="Accent.TButton"
        )
        launch_all_btn.pack(fill=tk.X, pady=2)
    
    def _refresh_software_list(self):
        """刷新软件列表显示"""
        # 清空现有列表
        for widget in self.scrollable_frame.winfo_children():
            widget.destroy()
        
        self.software_vars.clear()
        
        # 获取当前模式的软件列表
        current_mode = self.current_mode.get()
        software_list = self.config_manager.get_software_list(current_mode)
        
        if not software_list:
            # 显示空列表提示
            empty_label = ttk.Label(
                self.scrollable_frame,
                text="当前模式下没有软件，点击'添加软件'开始添加",
                foreground="gray"
            )
            empty_label.pack(pady=20)
            return
        
        # 创建软件条目
        for i, software in enumerate(software_list):
            self._create_software_item(i, software)
    
    def _create_software_item(self, index: int, software: Dict[str, str]):
        """创建单个软件条目"""
        item_frame = ttk.Frame(self.scrollable_frame)
        item_frame.pack(fill=tk.X, pady=2, padx=5)
        
        # 复选框
        var = tk.BooleanVar()
        self.software_vars.append(var)
        
        checkbox = ttk.Checkbutton(item_frame, variable=var)
        checkbox.pack(side=tk.LEFT, padx=(0, 10))
        
        # 软件信息
        info_frame = ttk.Frame(item_frame)
        info_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        name_label = ttk.Label(
            info_frame, 
            text=software.get('name', '未知软件'),
            font=("Arial", 10, "bold")
        )
        name_label.pack(anchor=tk.W)
        
        desc_label = ttk.Label(
            info_frame,
            text=software.get('description', '无描述'),
            foreground="gray"
        )
        desc_label.pack(anchor=tk.W)
        
        path_label = ttk.Label(
            info_frame,
            text=f"路径: {software.get('path', '')}",
            foreground="blue",
            font=("Arial", 8)
        )
        path_label.pack(anchor=tk.W)
        
        # 单独启动按钮
        launch_btn = ttk.Button(
            item_frame,
            text="启动",
            width=8,
            command=lambda idx=index: self._launch_single(idx)
        )
        launch_btn.pack(side=tk.RIGHT, padx=(10, 0))
    
    def _switch_mode(self, mode_name: str):
        """切换模式"""
        self.current_mode.set(mode_name)
        self.config_manager.set_current_mode(mode_name)
        self._refresh_software_list()
        self._refresh_mode_display()
    
    def _refresh_mode_display(self):
        """刷新模式显示"""
        # 重新创建整个界面以更新当前模式显示
        for widget in self.root.winfo_children():
            widget.destroy()
        self._create_widgets()
        self._refresh_software_list()
    
    def _open_mode_manager(self):
        """打开模式管理窗口"""
        ModeManagerWindow(self.root, self.config_manager, self._refresh_mode_display)

    def _add_software(self):
        """添加软件"""
        SoftwareEditWindow(
            self.root,
            self.config_manager,
            self.current_mode.get(),
            refresh_callback=self._refresh_software_list
        )

    def _edit_software(self):
        """编辑软件"""
        selected_indices = [i for i, var in enumerate(self.software_vars) if var.get()]
        if not selected_indices:
            messagebox.showwarning("提示", "请先选择要编辑的软件")
            return

        if len(selected_indices) > 1:
            messagebox.showwarning("提示", "请只选择一个软件进行编辑")
            return

        index = selected_indices[0]
        software_list = self.config_manager.get_software_list(self.current_mode.get())
        if 0 <= index < len(software_list):
            SoftwareEditWindow(
                self.root,
                self.config_manager,
                self.current_mode.get(),
                software_list[index],
                index,
                self._refresh_software_list
            )

    def _delete_software(self):
        """删除软件"""
        selected_indices = [i for i, var in enumerate(self.software_vars) if var.get()]
        if not selected_indices:
            messagebox.showwarning("提示", "请先选择要删除的软件")
            return

        if messagebox.askyesno("确认删除", f"确定要删除选中的 {len(selected_indices)} 个软件吗？"):
            # 从后往前删除，避免索引变化
            for index in sorted(selected_indices, reverse=True):
                self.config_manager.delete_software(self.current_mode.get(), index)
            self._refresh_software_list()

    def _select_all(self):
        """全选软件"""
        for var in self.software_vars:
            var.set(True)

    def _deselect_all(self):
        """取消全选"""
        for var in self.software_vars:
            var.set(False)

    def _launch_selected(self):
        """启动选中的软件"""
        selected_indices = [i for i, var in enumerate(self.software_vars) if var.get()]
        if not selected_indices:
            messagebox.showwarning("提示", "请先选择要启动的软件")
            return

        software_list = self.config_manager.get_software_list(self.current_mode.get())
        selected_software = [software_list[i] for i in selected_indices if i < len(software_list)]

        self._launch_software_list(selected_software)

    def _launch_all(self):
        """启动全部软件"""
        software_list = self.config_manager.get_software_list(self.current_mode.get())
        if not software_list:
            messagebox.showinfo("提示", "当前模式下没有软件可启动")
            return

        # 启动全部软件后直接关闭程序，无弹框提示
        def launch_all_callback(results):
            # 强制关闭程序，无需窗口焦点
            self.root.destroy()

        self.launcher.launch_software_list_async(software_list, 1.0, launch_all_callback)

    def _launch_single(self, index: int):
        """启动单个软件"""
        software_list = self.config_manager.get_software_list(self.current_mode.get())
        if 0 <= index < len(software_list):
            software = software_list[index]
            success, message = self.launcher.launch_software(
                software.get('path', ''),
                software.get('name', '')
            )

            if success:
                messagebox.showinfo("启动成功", f"已启动: {software.get('name', '')}")
            else:
                messagebox.showerror("启动失败", f"启动失败: {message}")

    def _launch_software_list(self, software_list: List[Dict[str, str]]):
        """启动软件列表"""
        if not software_list:
            return

        # 异步启动，避免界面卡顿
        def launch_callback(results):
            success_count = sum(1 for _, success, _ in results if success)
            total_count = len(results)

            if success_count == total_count:
                messagebox.showinfo("启动完成", f"成功启动 {success_count} 个软件")
            else:
                failed_software = [name for name, success, _ in results if not success]
                messagebox.showwarning(
                    "启动完成",
                    f"成功启动 {success_count}/{total_count} 个软件\n"
                    f"失败的软件: {', '.join(failed_software)}"
                )

        self.launcher.launch_software_list_async(software_list, 1.0, launch_callback)

    def run(self):
        """运行主窗口"""
        self.root.mainloop()
